package mainframe;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;


import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;
import javax.swing.plaf.metal.MetalBorders;

import architecture.Pipeline_Architecture;

public class MainFrame implements ActionListener{
	/**
	 * the main frame
	 */
	private JFrame jFrame;
	
	
	/**
	 * radio button
	 */
	private JRadioButton radioButton[];
	
	
	/**
	 * show element info in the infoPanel
	 */
	private JTable infoTable;
	
	
	/**
	 * buttons in the leftupPanel
	 */
	private JButton initButton,stepButton,autoButton,contButton;
	
	/**
	 * registers in the regPanel
	 */
	private JLabel	regLabel[];
	
	/**
	 * the value of PC  
	 */
	private JLabel	pcLabel ;
	
	/**
	 * goto address
	 */
	private JTextField addrField;
	
	/**
	 * memory table
	 */
	private JTable  memTable;
	
	private JScrollPane memjsp;
	
	/**
	 * button in the right Panel
	 */
	private JButton openButton,asmButton,showButton,aboutButton;
	
	
	
	
	/**
	 * the asm file
	 */
	private String [] asmArray;
	private int asmLen;
	
	/**
	 * kernel part
	 */
	private Pipeline_Architecture pipeline; 
	
	
	
	/**
	 * build the frame of MIPS
	 */
	public void buildFrame(){
		pipeline=new Pipeline_Architecture();
		pipeline.variable_init();
		pipeline.addForwarding();
		pipeline.addStall();	
		
		jFrame = new JFrame("MIPS");
		jFrame.getContentPane().setLayout(new BorderLayout());
		
		// set up the left up part
		JPanel leftPanel   = new JPanel(new BorderLayout());
		JPanel leftupPanel = new JPanel();
		JPanel ctrlPanel   = new JPanel(new GridLayout(2,2,10,5));
	
		initButton  = new JButton("Init");
		stepButton	= new JButton("Step");
		autoButton	= new JButton("AutoStep");
		contButton	= new JButton("Continuous");
		
		ctrlPanel.add(initButton);
		ctrlPanel.add(stepButton);
		ctrlPanel.add(autoButton);
		ctrlPanel.add(contButton);
		ctrlPanel.setBorder(createMyBorder("Command"));
		leftupPanel.add(ctrlPanel);
		ButtonGroup rbGroup = new ButtonGroup();
		
		radioButton	= new JRadioButton[4];
		radioButton[0] = new JRadioButton("Stall",true);
		radioButton[1] = new JRadioButton("Forwarding",false);
		radioButton[2] = new JRadioButton("Instruction",true);
		radioButton[3] = new JRadioButton("Data",false);
		JPanel radioPanel = new JPanel(new GridLayout(2,1,0,3));
		for (int i=0; i<2; ++i){
			rbGroup.add(radioButton[i]);
			radioPanel.add(radioButton[i]);
			radioButton[i].addActionListener(this);
		}
		radioPanel.setBorder(createMyBorder("ChooseFun"));
		leftupPanel.add(radioPanel);
		
		leftPanel.add(leftupPanel,BorderLayout.NORTH);
		
		
		// set up the left down part
		JPanel leftdnPanel = new JPanel(new BorderLayout());

		JPanel infoPanel = new JPanel(new BorderLayout());
		//JLabel infoLabel = new JLabel("Show Entity info:");
		//infoPanel.add(infoLabel,BorderLayout.NORTH);
		infoTable = new JTable(new String[][]{
				{"ALU","","","",""}
		}, new String[]{"Entity","src1","src2","op","result"});
		
		JScrollPane jsp = new JScrollPane(infoTable);
		jsp.setPreferredSize(new Dimension(100,150));
		jsp.setBorder(createMyBorder("EntityInfo"));
		jsp.setViewportBorder(new MetalBorders.ScrollPaneBorder());
		infoPanel.add(jsp,BorderLayout.SOUTH);
		
		JPanel regPanel = new JPanel(new GridLayout(8,4,2,1));	
		regPanel.setBorder(createMyBorder("Register"));
		regLabel	= new JLabel[32];
		for (int i=0; i<32; ++i){
			regLabel[i] = new JLabel("R" + i + "=00000000");
			regPanel.add(regLabel[i]);
		}	
		infoPanel.add(regPanel, BorderLayout.CENTER);
		
		leftdnPanel.add(infoPanel,BorderLayout.CENTER);
		leftPanel.add(leftdnPanel,BorderLayout.CENTER);
		leftPanel.setBorder(createMyBorder("MIPS"));
		

		// set up the right part
		JPanel rightPanel  = new JPanel(new BorderLayout());
		rightPanel.setBorder(createMyBorder("MemoryMonitor"));
		openButton	= new JButton("OpenFiles");
		asmButton	= new JButton("Assemble");
		showButton  = new JButton("ImageView");

		JPanel oaPanel = new JPanel();
		oaPanel.add(openButton);
		oaPanel.add(asmButton);
		oaPanel.add(showButton);
		oaPanel.setBorder(createMyBorder(""));
		
		JPanel rdPanel = new JPanel(new GridLayout(1,3,20,0));
		pcLabel = new JLabel("PC = 00000000");
		JPanel addrPanel = new JPanel(new BorderLayout());
		JLabel addrLabel = new JLabel("GoTo");
		addrField = new JTextField(8);
		addrPanel.add(addrLabel, BorderLayout.WEST);
		addrPanel.add(addrField, BorderLayout.CENTER);	
	
		rdPanel.add(pcLabel);
		rdPanel.add(addrPanel);

		rdPanel.setBorder(createMyBorder(""));
		addrField.addActionListener(this);
		
		ButtonGroup memGroup = new ButtonGroup();
		JPanel memRadioPanel = new JPanel(new GridLayout(1,2,2,2));
		for (int i=2; i<4; ++i){
			memGroup.add(radioButton[i]);
			memRadioPanel.add(radioButton[i]);
			radioButton[i].addActionListener(this);
		}
		memRadioPanel.setBorder(createMyBorder(""));
		
		aboutButton = new JButton("About");
		aboutButton.setPreferredSize(new Dimension(70,20));
		JPanel aboutPanel = new JPanel();
		aboutPanel.add(aboutButton);
		
		JPanel midMemPanel = new JPanel(new BorderLayout());
		midMemPanel.add(memRadioPanel,BorderLayout.WEST);
		midMemPanel.add(aboutPanel,BorderLayout.CENTER);
		
		JPanel rightUpPanel = new JPanel(new BorderLayout());
		rightUpPanel.add(oaPanel, BorderLayout.NORTH);
		rightUpPanel.add(rdPanel, BorderLayout.CENTER);
		rightUpPanel.add(midMemPanel, BorderLayout.SOUTH);
		
		rightPanel.add(rightUpPanel, BorderLayout.NORTH);
		
		
		memTable = new MemTable();
		memjsp = new JScrollPane(memTable);
		rightPanel.add(memjsp, BorderLayout.CENTER);
		
		/*
		leftPanel.setBorder(new MetalBorders.Flush3DBorder());
		rightPanel.setBorder(new MetalBorders.Flush3DBorder());
		leftupPanel.setBorder(new MetalBorders.Flush3DBorder());
		leftdnPanel.setBorder(new MetalBorders.Flush3DBorder());
		*/

		// add action listener
		initButton.addActionListener(this);
		stepButton.addActionListener(this);
		autoButton.addActionListener(this);
		contButton.addActionListener(this);
		openButton.addActionListener(this);
		asmButton.addActionListener(this);
		showButton.addActionListener(this);
		aboutButton.addActionListener(this);

		jFrame.getContentPane().add(leftPanel,BorderLayout.WEST);
		jFrame.getContentPane().add(rightPanel,BorderLayout.CENTER);
		jFrame.setBounds(250,250,750,500);
		jFrame.setVisible(true);
		jFrame.setResizable(false);
		jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);   
		
		
	}
	
	private Border createMyBorder(String name){
		Border border = BorderFactory.createEtchedBorder();
		border = BorderFactory.createTitledBorder(border, name, 
				TitledBorder.LEFT, TitledBorder.TOP ,new Font("Serif",Font.BOLD,15) , Color.blue);
		return border;
	}
	
	// update the frame
	public void update() {
		int reg[] = pipeline.registers.getRegisters();
		for (int i=0;i<32;i++){
			regLabel[i].setText("R" + i + "=" + Integer.toHexString(reg[i]));
			regLabel[i].updateUI();
		}
		infoTable.updateUI();
		pcLabel.updateUI();
		memTable.updateUI();
	}
	
	
	
	@Override
	public void actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub
		if (e.getSource() == openButton){
			OpenFile openFile = new OpenFile();
			openFile.doModel(jFrame);
			asmArray = openFile.getAsmArray();
			asmLen = openFile.getAsmLen();
			MemTableModel mtModel=(MemTableModel)memTable.getModel();
			mtModel.setAsmArray(asmArray, asmLen);
			mtModel.updateContent();
			memTable.updateUI();
		}
		else if(e.getSource() == asmButton) {
			
		}
		else if(e.getSource() == showButton) {
			JFrame frame = new JFrame("Pipeline");
			JLabel label = new JLabel();
			label.setIcon(new ImageIcon("pipeline.jpg"));
			frame.add(label);
			frame.setBounds(150, 150, 1000, 800);
			frame.setResizable(false);
			frame.setVisible(true);
			frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		}
		else if(e.getSource() == aboutButton) {
			String info = "=========Made by========\n" +
					" Jing    DavidDragon \n" +
					" Wosan   ChampionSong\n" +
					" <Tsinghua-CS>        \n" +
					"=======================";
			JOptionPane.showMessageDialog(jFrame, info,
		            "Author", JOptionPane.INFORMATION_MESSAGE);
			
		}
		else if(e.getSource() == radioButton[0]) {
			
		}
		else if(e.getSource() == radioButton[1]) {
			
		}
		else if(e.getSource() == radioButton[2]) {
			
		}
		else if(e.getSource() == radioButton[3]) {
			
		}
		else if(e.getSource() == initButton) {
			pipeline.variable_init();
			this.update();
		}
		else if(e.getSource() == stepButton) {
			pipeline.clockEvent();
			this.update();
		}
		else if(e.getSource() == autoButton) {
			for(int i=0; i<asmLen; ++i) {
				Thread thread = new Thread() {
					public void run(){
						pipeline.clockEvent();
						update();
						try {
							sleep((long)(Math.random()*2000));
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
					
				};
				thread.start();
			}
		}
		else if(e.getSource() == contButton) {
			for(int i=0; i<asmLen; ++i) {
				Thread thread = new Thread() {
					public void run(){
						pipeline.clockEvent();
						try {
							sleep((long)(Math.random()*2000));
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
					
				};
				thread.start();
			}	
			this.update();
		}
		else if(e.getSource() == addrField) {
			String addr = addrField.getText().trim();
			int vis = memjsp.getVerticalScrollBar().getVisibleAmount();
			int cur = Integer.parseInt(addr);
			int high = memTable.getRowHeight();
			((MemTable)memTable).setBackground(cur, Color.CYAN);
			
			cur = cur * high;
			
			int pos;
			pos = cur - vis/2 + high;
			if (pos > 0)
				memjsp.getVerticalScrollBar().setValue(pos);
			else
				memjsp.getVerticalScrollBar().setValue(0);
			
			memTable.updateUI();
		}
		
		
	}

	
	

}
